using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace MicroLink.StsDev2008AddIn.DeploymentFiles
{
    public class CabDdfBuilder
    {
        public static void Create(string projectDirectory, string buildDirectory, string targetName)
        {
            Create(
                projectDirectory
                , buildDirectory
                , targetName
                , string.Format(@"{0}\RootFiles\TEMPLATE\FEATURES", projectDirectory)
                , string.Format(@"{0}\RootFiles\TEMPLATE", projectDirectory)
                , string.Format(@"{0}\RootFiles\ISAPI", projectDirectory)
                , string.Format(@"{0}\RootFiles\RESOURCES", projectDirectory)
                );
        }

        public static void Create(
            string projectDirectory
            , string buildDirectory
            , string targetName
            , string featuresFolder
            , string templateFolder
            , string isapiFolder
            , string resourcesFolder
            )
        {
            StreamWriter writer = new StreamWriter(buildDirectory + targetName + ".ddf");
            writer.WriteLine("; Generated at " + DateTime.Now.ToString());
            writer.WriteLine();
            writer.WriteLine(".OPTION EXPLICIT");
            writer.WriteLine(".Set CabinetNameTemplate=" + targetName + ".wsp");
            writer.WriteLine(".set DiskDirectoryTemplate=CDROM");
            writer.WriteLine(".Set CompressionType=MSZIP");
            writer.WriteLine(".Set UniqueFiles=off");
            writer.WriteLine(".Set Cabinet=on");
            writer.WriteLine(".Set DiskDirectory1=\"" + buildDirectory + "\"");
            writer.WriteLine();

            writer.WriteLine(";*** Solution manifest");
            writer.WriteLine(buildDirectory + @"\manifest.xml");

            if (!File.Exists(buildDirectory + @"\manifest.xml"))
                throw new FileNotFoundException("Manifest file does not exist");

            XmlDocument manifest = new XmlDocument();
            manifest.Load(buildDirectory + @"\manifest.xml");

            XmlNamespaceManager ns = new XmlNamespaceManager(manifest.NameTable);
            ns.AddNamespace("sp", "http://schemas.microsoft.com/sharepoint/");

            XmlNodeList assemblies = manifest.DocumentElement.SelectNodes(@"//sp:Assembly", ns);

            writer.WriteLine("");
            writer.WriteLine(";*** Assembly files");
            foreach (XmlNode assembly in assemblies)
            {
                writer.WriteLine("\"" + buildDirectory + assembly.Attributes["Location"].Value + "\"");
            }

            string[] webpartFiles = Directory.GetFiles(projectDirectory, "*.webpart");
            if (webpartFiles.Length > 0)
            {
                writer.WriteLine("");
                writer.WriteLine(";*** Global webpart Files ***");
                foreach (string webpartFile in webpartFiles)
                    writer.WriteLine(webpartFile);
            }

            string[] dwpFiles = Directory.GetFiles(projectDirectory, "*.dwp");
            if (dwpFiles.Length > 0)
            {
                writer.WriteLine("");
                writer.WriteLine(";*** Global dwp Files ***");
                foreach (string dwpFile in dwpFiles)
                    writer.WriteLine(dwpFile);
            }


            if (Directory.Exists(featuresFolder))
            {
                // write FeatureFiles
                writer.WriteLine("");
                writer.WriteLine(";***********************************");
                writer.WriteLine(";***     FeatureFiles section    ***");
                writer.WriteLine(";***********************************");
                WriteFeatureFiles(writer, featuresFolder, featuresFolder);
                writer.WriteLine();
            }

            if (Directory.Exists(templateFolder))
            {
                // write TemplateFiles
                writer.WriteLine("");
                writer.WriteLine(";***********************************");
                writer.WriteLine(";***     TemplateFiles section   ***");
                writer.WriteLine(";***********************************");
                WriteTemplateFiles(writer, templateFolder, templateFolder);
                writer.WriteLine();
            }

            if (Directory.Exists(isapiFolder) || Directory.Exists(resourcesFolder))
            {
                // write RootFiles
                writer.WriteLine("");
                writer.WriteLine(";*******************************");
                writer.WriteLine(";***     RootFiles section   ***");
                writer.WriteLine(";*******************************");
                WriteRootFiles(writer, projectDirectory, projectDirectory);
                writer.WriteLine();
            }

            writer.Close();
        }

        static void WriteFeatureFiles(StreamWriter writer, string path, string featuresFolder)
        {
            if ((Directory.GetFiles(path).Length > 0) &&
                 (path != featuresFolder))
            {
                // write files
                int PathOffset = (featuresFolder + @"\").Length;
                writer.WriteLine();
                writer.WriteLine(";*** add files for " + path.Substring(PathOffset) + " feature");
                writer.WriteLine(".Set DestinationDir=" + path.Substring(PathOffset));
                foreach (string file in Directory.GetFiles(path))
                {
                    writer.WriteLine("\"" + file + "\"");
                }

            }

            foreach (string folder in Directory.GetDirectories(path))
            {
                WriteFeatureFiles(writer, folder, featuresFolder);
            }
        }

        static void WriteTemplateFiles(StreamWriter writer, string path, string templatesFolder)
        {
            // do nothing for folders in FEATURES folder
            if (path.Contains("FEATURES"))
            {
                return;
            }
            // write files
            if ((Directory.GetFiles(path).Length > 0) &&
                (path != templatesFolder))
            {
                int PathOffset = (templatesFolder + @"\").Length;
                writer.WriteLine("");
                writer.WriteLine(".Set DestinationDir=" + path.Substring(PathOffset));
                foreach (string file in Directory.GetFiles(path))
                {
                    writer.WriteLine("\"" + file + "\"");
                }
            }

            foreach (string folder in Directory.GetDirectories(path))
            {
                WriteTemplateFiles(writer, folder, templatesFolder);
            }
        }

        static void WriteRootFiles(StreamWriter writer, string path, string rootFilesFolder)
        {
            // do nothing for folders in TEMPLATE folder
            if (path.Contains("TEMPLATE"))
            {
                return;
            }
            // write files
            if ((Directory.GetFiles(path).Length > 0) &&
                (path != rootFilesFolder))
            {
                int PathOffset = (rootFilesFolder + @"\").Length;
                writer.WriteLine("");
                writer.WriteLine(".Set DestinationDir=" + path.Substring(PathOffset));
            }
            foreach (string file in Directory.GetFiles(path))
            {
                writer.WriteLine("\"" + file + "\"");
            }

            foreach (string folder in Directory.GetDirectories(path))
            {
                WriteRootFiles(writer, folder, rootFilesFolder);
            }
        }
    }
}
